#pragma once 

#include "type.h"

#include "vector2.h"
#include "vector3.h"

namespace RenderSystem
{
	class StaticMesh;

	// Temporary vertex for utility class
	struct FUtilVertex
	{
		Common::Vector3		Position;
		Common::Vector2		UVs[4];
		FColor				Color;
		DWORD				SmoothingMask;
		INT					FragmentIndex;
		bool				bOverrideTangentBasis;
		Common::Vector3		TangentX;
		Common::Vector3		TangentY;
		Common::Vector3		TangentZ;
	};

	/**
	*
	* This utility class builds on D3DX functionality.
	* Used for editor helpers.
	*
	*/
	class FD3DMeshUtilities
	{

	private:

		/**
		* Creates a D3DXMESH from a FStaticMeshRenderData
		* @param Triangles The triangles to create the mesh from.
		* @param bRemoveDegenerateTriangles True if degenerate triangles should be removed
		* @param OutD3DMesh Mesh to create
		* @return Boolean representing success or failure
		*/
		bool ConvertStaticMeshTrianglesToD3DXMesh(
			const std::vector<FStaticMeshTriangle>& Triangles,
			const bool bRemoveDegenerateTriangles,
			TRefCountPtr<ID3DXMesh>& OutD3DMesh
			);

		/**
		* Creates a FStaticMeshRenderData from a D3DXMesh
		* @param DestMesh Destination mesh to extract to
		* @param NumUVs Number of UVs
		* @param Elements Elements array
		* @return Boolean representing success or failure
		*/
		bool ConvertD3DXMeshToStaticMesh(
			TRefCountPtr<ID3DXMesh>& D3DMesh, 
			StaticMeshRenderData& DestMesh, 
			INT NumUVs, 
			std::vector<FStaticMeshElement>& Elements, 
			bool bClearDestElements
			);

	public:

		FD3DMeshUtilities() {}

		/**
		* Generates a simplified LOD from a static mesh
		* @param SourceStaticMesh - The input mesh.  Can be the same as the output mesh, as long as the desired LOD is different.
		* @param DestStaticMesh - Output mesh.  Can be the same as the input mesh
		* @param DesiredLOD - The LOD level to generate the simplified mesh for
		* @param DesiredTriangles - The desired triangle count for the LOD. Resulting triangle count may not be desired triangle count.
		* @return TRUE if successful
		*/
		bool GenerateLOD( StaticMesh* SourceStaticMesh, StaticMesh* DestStaticMesh, INT DesiredLOD, INT DesiredTriangles );

		/**
		* Generates a unique UV layout for a static mesh
		* @param StaticMesh - The input/output mesh
		* @param LODIndex - The LOD level
		* @param TexCoordIndex - Index of the uv channel to overwrite or create
		* @param bKeepExistingCoordinates - True to preserve the existing charts when packing
		* @param MinChartSpacingPercent - Minimum distance between two packed charts (0.0-100.0)
		* @param BorderSpacingPercent - Spacing between UV border and charts (0.0-100.0)
		* @param bUseMaxStretch - True if "MaxDesiredStretch" should be used; otherwise "MaxCharts" is used
		* @param InFalseEdgeIndices - Optional list of raw face edge indices to be ignored when creating UV seams
		* @param MaxCharts - In: Max number of charts to allow; Out:Number of charts generated by the uv unwrap algorithm.
		* @param MaxDesiredStretch - The amount of stretching allowed. 0 means no stretching is allowed, 1 means any amount of stretching can be used. 
		* @return TRUE if successful
		*/
		bool GenerateUVs(
			StaticMesh* StaticMesh,
			UINT LODIndex,
			UINT TexCoordIndex,
			bool bKeepExistingCoordinates,
			FLOAT MinChartSpacingPercent,
			FLOAT BorderSpacingPercent,
			bool bUseMaxStretch,
			const INT* InFalseEdgeIndices,
			UINT& MaxCharts,
			FLOAT& MaxDesiredStretch
			);


	private:

		/**
		* Called during unique UV set generation to allow us to update status in the GUI
		*
		* @param	InPercentDone	Scalar (0-1) of percent currently complete
		* @param	InUserData		User data pointer
		*/
		static HRESULT __stdcall GenerateUVsStatusCallback( FLOAT InPercentDone, void* InUserData );

	};
}